/**
 * 
 */
package com.luxsoft.siipap.em.replica.ui.tasks;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.StringWriter;
import java.lang.ref.WeakReference;
import java.text.MessageFormat;

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;

import org.apache.log4j.Appender;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.apache.log4j.PatternLayout;
import org.apache.log4j.WriterAppender;
import org.apache.log4j.spi.LoggingEvent;

import com.jgoodies.forms.builder.ButtonBarBuilder;
import com.jgoodies.forms.builder.PanelBuilder;
import com.jgoodies.forms.layout.CellConstraints;
import com.jgoodies.forms.layout.FormLayout;
import com.jgoodies.uif.component.UIFButton;
import com.jgoodies.uifextras.panel.HeaderPanel;
import com.luxsoft.siipap.swing.controls.SXAbstractDialog;

/**
 * Dialogo para la ejecucion de tareas
 * 
 * @author Ruben Cancino
 *
 */
public class TaskDialog extends SXAbstractDialog{
	
	private HeaderPanel header;
	private WeakReference<SwingWorker> workerRef;
	private PropertyChangeListener workerHandler=new WorkerHandler();

	public TaskDialog(String title) {
		super(title);
		header=new HeaderPanel(title,"");
	}

	@Override
	protected JComponent buildHeader() {
		return header;
	}

	public HeaderPanel getHeader(){
		return header;
	}
	
	
	public void registerWorker(SwingWorker worker){
		workerRef=new WeakReference<SwingWorker>(worker);
		worker.addPropertyChangeListener(workerHandler);
	}


	private JPanel mainPanel;

	
	@Override
	protected JComponent buildContent() {
		FormLayout layout=new FormLayout("f:250dlu:g","f:15dlu,3dlu,p,3dlu,p");
		PanelBuilder builder=new PanelBuilder(layout);
		builder.setDefaultDialogBorder();
		CellConstraints cc=new CellConstraints();
		builder.add(buildProgressPanel(),cc.xy(1, 1));
		builder.add(buildButtonBar(), cc.xy(1, 3));
		builder.add(buildLogPanel(),cc.xy(1,5));
		mainPanel=builder.getPanel();
		logPanel.addComponentListener(new ComponentAdapter(){
			public void componentHidden(ComponentEvent e) {
				actualizarBotonDeDetalles();
			}
			@Override
			public void componentShown(ComponentEvent e) {
				actualizarBotonDeDetalles();
			}
			
		});
		logPanel.setVisible(showHide);
		return mainPanel;
	}	

	private void actualizarBotonDeDetalles(){
		String msg="{0} Detalles";
		if(logPanel.isVisible())
			msg=MessageFormat.format(msg, "<<","");
		else
			msg=MessageFormat.format(msg, ">>","");
		showDetailAction.putValue(Action.NAME, msg);
	}
	
	public static final String SIMPLE_PATTERN_LAYOUT="%-5p  %x - %m";
	
	public static final String DETAIL_PATTERN_LAYOT="%-19d{dd/MM hh:mm:ss,SSS} [%t] %-5p %c %x - %m";
	
	public void registerDefaultLogger(){
		//registerDetailLogHandler(Logger.getRootLogger());
		Logger log=Logger.getLogger("IMPORTADORES");
		log.setLevel(Level.INFO);
		registerDetailLogHandler(log);
	}
	
	public  Appender registerDetailLogHandler(final Logger logger){
		PatternLayout layout = new PatternLayout(SIMPLE_PATTERN_LAYOUT);
		return registerDetailLogHandler(logger,layout);
	}
	
	public  Appender registerDetailLogHandler(final Logger logger,PatternLayout layout){
		StringWriter writer=new StringWriter();
		WriterAppender appender=new WriterAppender(){
			public void append(LoggingEvent loggingEvent) {
				final String message = this.layout.format(loggingEvent);
				// Append formatted message to textarea using the Swing Thread.
				SwingUtilities.invokeLater(new Runnable() {
					public void run() {
						log(message);
					}
				});				
			}
		};		
		appender.setWriter(writer);
		appender.setLayout(layout);
		logger.addAppender(appender);
		return appender;
	}
	
	public void unregisterLoggers(){
		
	}
	
	public void log(String msg){
		infoArea.append(msg+"\n");
	}
	
	JTextArea infoArea;
	JComponent logPanel;
	
	private JComponent buildLogPanel(){
		logPanel=new JPanel(new BorderLayout()); 
		infoArea=new JTextArea(10,10);
		infoArea.setBackground(Color.BLACK);
		infoArea.setForeground(Color.GREEN);
		infoArea.setEditable(false);
		
		JScrollPane sp=new JScrollPane(infoArea);
		logPanel.add(sp);
		return logPanel;
	}
	
	protected JProgressBar progress;
	
	private JComponent buildProgressPanel(){
		progress=createProgressBar();
		progress.setVisible(false);
		
		JPanel progressPanel=new JPanel(new BorderLayout());
		progressPanel.add(progress,BorderLayout.CENTER);
		return progressPanel;
	}
	
	protected JProgressBar createProgressBar(){
		JProgressBar bar=new JProgressBar(1,100);
		bar.setStringPainted(true);
		return bar;
	}
	
	protected JComponent buildButtonBar() {
		
		ButtonBarBuilder builder =new ButtonBarBuilder();
		builder.addGlue();
		builder.addGridded(createStartButton(true));
		builder.addRelatedGap();
		builder.addGridded(createStopButton());
        builder.addUnrelatedGap();
        builder.addGridded(createDetailButton());
        return builder.getPanel();        
	}
	

	protected UIFButton createStartButton(boolean isDefault) {
		UIFButton okButton = new UIFButton(getStartAction());
		if (isDefault)
			setDefaultButton(okButton);
		return okButton;
	}
	
	protected UIFButton createStopButton() {
		return new UIFButton(getStopAction());
	}
	protected UIFButton createDetailButton() {
		return new UIFButton(getShowDetailAction());
	}

	private Action startAction;	
	private Action stopAction;
	private Action showDetailAction;

	public Action getStartAction() {
		if (startAction == null) {
			startAction = new AbstractAction("Iniciar") {
				public void actionPerformed(ActionEvent e) {
					start();
				}
			};
		}
		return startAction;
	}	

	public Action getStopAction() {
		if (stopAction == null) {
			stopAction = new AbstractAction("Detener") {
				public void actionPerformed(ActionEvent e) {
					stop();
				}
			};
			stopAction.setEnabled(false);
		}
		return stopAction;
	}
	
	public Action getShowDetailAction() {
		if (showDetailAction == null) {
			showDetailAction = new AbstractAction("Detalle") {
				public void actionPerformed(ActionEvent e) {
					showHideDetail();
				}
			};
		}
		return showDetailAction;
	}
	
	public void close(){
		if( (workerRef!=null) && (workerRef.get()!=null)){
			if(!workerRef.get().isDone())
				workerRef.get().cancel(true);
			workerRef.get().removePropertyChangeListener(workerHandler);
		}
		super.close();
	}

	
	public void start() {
		if((workerRef!=null) && (workerRef.get()!=null)){
			workerRef.get().execute();
		}
		
	}
	
	

	public void stop() {
		if((workerRef!=null) && (workerRef.get()!=null)){			
			workerRef.get().cancel(true);
		}
		
	}
	
	private boolean showHide=false;
	
	public void showHideDetail(){
		showHide=!showHide;
		logPanel.setVisible(showHide);
		pack();
		
	}
	
	public void taskStarted(){
		header.setDescription("Ejecutando tarea");
		stopAction.setEnabled(true);
		startAction.setEnabled(false);
		progress.setVisible(true);
	}
	
	public void taskStoped(){
		header.setDescription("Tarea terminada");
		stopAction.setEnabled(false);
		startAction.setEnabled(false);
		if( (workerRef!=null) && (workerRef.get()!=null))
			workerRef.get().removePropertyChangeListener(workerHandler);
	}

	/**
	 * Handler para determinar el estado segun el worker
	 * 
	 * @author Ruben Cancino
	 *
	 */
	public  class WorkerHandler implements PropertyChangeListener{

		public void propertyChange(PropertyChangeEvent evt) {
			if ("progress".equals(evt.getPropertyName())) {
                progress.setValue((Integer)evt.getNewValue());
            }else if("state".equals(evt.getPropertyName())){
            	SwingWorker.StateValue va=(SwingWorker.StateValue)evt.getNewValue();
            	switch (va) {
				case STARTED:
					taskStarted();
					break;
				case DONE:
					taskStoped();
					break;
				case PENDING:
					break;
				default:
					break;
				}
            }
		}
		
	}
	
	
	
	public static void main(String[] args) {
		TaskDialog dialog=new TaskDialog("Test");
		dialog.open();
		
	}
}